package lv.dysnomia.portal.web

import lv.dysnomia.server.entities.MediaFileDAO
import com.google.appengine.api.datastore.Text
import lv.dysnomia.songs.server.wiki.WikiProc
import lv.dysnomia.songs.server.wiki.WikiParser
import java.lang.{ Integer => JavaInteger }
import java.util.{ Map => JavaMap }
import java.util.{ HashMap, List => JavaList }
import javax.servlet.http.{ HttpServlet, HttpServletRequest, HttpServletResponse }

import scala.collection.immutable.Map

import lv.dysnomia.server.entities.{ Song, SongDAO }

import net.sf.jsr107cache.{ Cache, CacheException, CacheFactory, CacheManager }
import com.google.appengine.api.memcache.stdimpl.GCacheFactory;

class SimpleController extends AbstractController {

  var cache: Cache = null

  def modelAndView(request: HttpServletRequest, response: HttpServletResponse): (Map[String, AnyRef], String) = {
    val pathInfo = request.getPathInfo
    val method = request.getMethod
    pathInfo match {
      case "/index.html" => index
      case "/all-songs.html" => allSongs(request.getParameter("offset"))
      case "/books.html" => books
      case "/sources.html" => sources
      case "/view-song.html" => viewSong(request.getParameter("label"))
      case _ => (Map("pathInfo" -> pathInfo, "method" -> "GET"), "notFound")
    }
  }

  def initCache(): Unit = {
    val props: JavaMap[Int, AnyRef] = new HashMap[Int, AnyRef]
    props.put(GCacheFactory.EXPIRATION_DELTA, 3600.asInstanceOf[AnyRef])
    try {
      val cacheFactory: CacheFactory = CacheManager.getInstance.getCacheFactory
      cache = cacheFactory.createCache(props);
    } catch {
      case e1: CacheException => {}
      case _ => {}
    }
  }

  def index(): (Map[String, AnyRef], String) = {
    if (cache == null) {
      initCache
    }
    val songs: JavaList[Song] = SongDAO.getSongs
    cache.put("count", songs.size)
    (Map("songs" -> songs), "index")
  }
  def books(): (Map[String, AnyRef], String) = (Map.empty[String, AnyRef], "books")
  def sources(): (Map[String, AnyRef], String) = (Map.empty[String, AnyRef], "sources")

  def refreshCount(): JavaInteger = {
    if (cache == null) {
      initCache
    }
    if (!cache.containsKey("count")) {
      val songs: JavaList[Song] = SongDAO.getSongs
      cache.put("count", new JavaInteger(songs.size))
    }
    cache.get("count").asInstanceOf[JavaInteger]
  }

  def allSongs(offset: String): (Map[String, AnyRef], String) = {
    val currentOffset = if (offset != null) offset.toInt else 0
    val songs: JavaList[Song] = SongDAO.getSongs(currentOffset)
    val count = refreshCount.intValue
    val range = new Range(0, count, 2)
    (Map("songs" -> songs,
      "currentOffset" -> currentOffset.asInstanceOf[JavaInteger],
      "count" -> refreshCount,
      "offsets" -> range.toArray), "all-songs")
  }

  def viewSong(label: String): (Map[String, AnyRef], String) = {
    val s = SongDAO.getSongByLabel(label)
    val lyrics = if (s.getLyrics != null) {
      val lyricsString = s.getLyrics.getValue
      val exprs = WikiParser.parse(lyricsString)
      WikiProc.eval(exprs)
    } else ""
    val svgBlobKey = MediaFileDAO.getKeyByFname(label + ".svg")
    val pngBlobKey = MediaFileDAO.getKeyByFname(label + ".png")
    val midiBlobKey = MediaFileDAO.getKeyByFname(label + ".midi")
    (Map("song" -> s,
      "lyrics" -> lyrics,
      "svgBlobKey" -> svgBlobKey, 
      "pngBlobKey" -> pngBlobKey,
      "midiBlobKey" -> midiBlobKey), "view-song")
  }
}